package NetWork;

import java.io.File;
import java.text.NumberFormat;
import java.util.logging.Level;
import java.util.logging.Logger;
import odeToJava.Erk;
import odeToJava.modules.Btableau;
import odeToJava.modules.Span;
import IoTools.AnalyserCellByTime;
import IoTools.AnalyserCellByCell;
import IoTools.AnalyserTools;
import IoTools.ParamSet;
import IoTools.XlsExporter;

/**
 *
 * @author citizen5589 && mawakien0
 */
public class Simulation implements Runnable {

    /**
     * @param args the command line arguments
     */
    private static double step = 0.05D;
    private static MainWindow win;
    private static boolean patient;
    private static boolean done;
    private static int number;

    /**
     * 
     */
    @SuppressWarnings("empty-statement")
    public void run() {

        win = new MainWindow();
        win.setVisible(true);

        patient = true;
        done = false;

        int compteur = 0;
        // Gamma, Delta, and GammaMin, GammaStep, etc
        ParamSet p = new ParamSet();

        while (!done) {
            win.setInfoLabel("set values or choose a pre-set model then press simulate button");
            compteur = 0;
            win.setTotalProgress(0);
            // there is a waiting loop (for entering new values in the panel)
            System.out.println("Waiting...");
            while (patient) {
                try {
                    Thread.sleep(100);
                } catch (InterruptedException ex) {
                    Logger.getLogger(Simulation.class.getName()).log(Level.SEVERE, null, ex);
                }

            }

            // get values from the panel
            p.setTotalTime(win.getTotalTime());
            p.setGammaLoop(getNbOfLoop(win.getGammaStart(), win.getGammaEnd(), win.getGammaStep()));
            p.setDeltaLoop(getNbOfLoop(win.getDeltaStart(), win.getDeltaEnd(), win.getDeltaStep()));
            p.setGammaStep(win.getGammaStep());
            p.setDeltaStep(win.getDeltaStep());

            p.setGammaMin(win.getGammaStart());
            p.setDeltaMin(win.getDeltaStart());
            p.setAlphaMin(win.getAlphaStart());
            p.setBetaMin(win.getBetaStart());
            p.setGammaEnd(win.getGammaEnd());
            p.setDeltaEnd(win.getDeltaEnd());
            p.setPulse1Start(win.getPulse1Start());
            p.setPulse1End(win.getPulse1End());
            p.setPulse2Start(win.getPulse2Start());
            p.setPulse2End(win.getPulse2End());

            // creation of epilepticTable that will stock results from analyser
            int epilepticTable[][] = new int[p.GammaLoop()][p.DeltaLoop()];

            // creation of an AnalyserCellByCell
            AnalyserCellByCell cellAnalyser = new AnalyserCellByCell();

            // build a new file where stock results
            String root = "Results_" + number + "/";
            File file = new File(root);
            boolean exists = file.exists();
            while (exists) {
                number++;
                root = "Results_" + number + "/";
                file = new File(root);
                exists = file.exists();
            }
            new File(root).mkdir();

            /* Start simulation loop */


            Double gammaTemp = p.GammaMin(), deltaTemp = p.DeltaMin();
            int i=0, j=0;            
            //these two following lines doesn't work well (don't know why! it's an very evil fraction trouble)   
            //for (gammaTemp = p.GammaMin(), i=0; gammaTemp <= p.GammaEnd(); gammaTemp += p.GammaStep(), i++) {   
                //for (deltaTemp = p.DeltaMin(), j=0; deltaTemp <= p.DeltaEnd(); deltaTemp += p.DeltaStep(), j++) {
             
            while (i < p.GammaLoop()) {
                while (j < p.DeltaLoop()) {
                    System.out.println("gamma:"+gammaTemp+"  delta:"+deltaTemp+"  i:"+i+"  j:"+j+"  gammaLoop:"+p.GammaLoop()+"  deltaLoop:"+p.DeltaLoop());
                    win.setInfoLabel("g:" + AnalyserTools.prettyFormat(gammaTemp)
                            + " d:" + AnalyserTools.prettyFormat(deltaTemp) + " rk4 resolution...");
                    compteur++;

                    // inits for omega
                    Omega omega = new Omega();
                    Omega.initValues(gammaTemp, deltaTemp, p.AlphaMin(), p.BetaMin(), p.Pulse1Start(), p.Pulse1End(), p.Pulse2Start(), p.Pulse2End());

                    // Some string used by the path
                    String name = createNameOfFile(gammaTemp, deltaTemp, p.AlphaMin(), p.BetaMin(), p.Pulse1Start(), p.Pulse1End(), p.Pulse2Start(), p.Pulse2End(), p.TotalTime());
                    String path = name + "/";
                    String nameOfFile = name + ".txt";
                    // Create Path
                    new File(root + path).mkdir();

                    // begin resolution
                    Span timex = new Span(0.0D, p.TotalTime());
                    double[] init = {0.0D, 0.0D, 0.0D, 0.0D, 0.0D, 0.0D, 0.0D, 0.0D, 0.0D, 0.0D, 0.0D, 0.0D, 0.0D, 0.0D, 0.0D, 0.0D, 0.0D, 0.0D, 0.0D, 0.0D, 0.0D, 0.0D};
                    Btableau bt = new Btableau("erk4");
                    String s1 = new String(root + path + nameOfFile);
                    String s2 = new String("Stats_Off");
                    int nPoints = (int) (p.TotalTime() / step);
                    Erk.erk(omega, timex, init, step, bt, s1, s2, nPoints);

                    // if "export to .png" have been selected
                    if (win.getWriteCheck()) {
                        
                        win.setInfoLabel("g:" + gammaTemp + " d:" + deltaTemp + " plotting ");
                        // pass the name of simulation to the AnalyserCellByTime ( whitch create png from datas )
                        AnalyserCellByTime analyser = new AnalyserCellByTime(root + path, name, win.getWriteCheck());
                        epilepticTable[i][j] = analyser.isEpileptic();
                        cellAnalyser.Add(analyser.getResult());
                        // and finally delete the very big .txt file
                        File deleteFile = new File(root + path + nameOfFile);
                        deleteFile.delete();
                    }
                    win.setTotalProgress(compteur * 100 / (p.GammaLoop() * p.DeltaLoop()));// update progress bar

                gammaTemp = AnalyserTools.Round(gammaTemp, 6);
                deltaTemp = AnalyserTools.Round(deltaTemp, 6);
                deltaTemp += p.DeltaStep(); j++;
                }// end of deltaTemp loop
                gammaTemp += p.GammaStep(); i++;

            }// end of gammaTemp loop


            // export the epilepticTable into a xls file
            new XlsExporter(root, epilepticTable, p.GammaMin(), p.GammaStep(), p.DeltaMin(), p.DeltaStep());
            // export graph of cells behavior
            cellAnalyser.PlotEmAll(root, p);

            setPatient();
        }
    }
    /**
     * 
     * @return
     */
    public static double getStep() {
        return step;
    }
    
    /**
     * 
     */
    public static void setPatient() {
        if (patient) {
            patient = false;
        } else {
            patient = true;
        }
    }

    public int getNbOfLoop(double start, double End, double step) {
        int temp = 1;
        if (End != 0) {
            temp = (int) (((1000 * End) - (1000 * start)) / (1000 * step)) + 1;
            //System.out.println("LOOP : " + temp);
            return temp;
        } else {
            //System.out.println("LOOP : " + temp);
            return temp;
        }

    }

    public String createNameOfFile(double gamma,
            double delta,
            double alpha,
            double beta,
            double start,
            double end,
            double startBis,
            double endBis,
            double tTime) {
        NumberFormat nbFormat = NumberFormat.getInstance();
        nbFormat.setMinimumFractionDigits(4); //nb de chiffres apres la virgule

        //donne la chaine representant le double avec 2 chiffres apres la virgules
        if (endBis == 0) {
            return "G" + nbFormat.format(gamma) + "_D" + nbFormat.format(delta) +
                    "_A" + nbFormat.format(alpha) + "_B" + nbFormat.format(beta) +
                    "_Ps" + (int) (start) + "_Pe" + (int) (end) + "_TT" + (int) (tTime);
        } else {
            return "G" + nbFormat.format(gamma) + "_D" + nbFormat.format(delta) +
                    "_A" + nbFormat.format(alpha) + "_B" + nbFormat.format(beta) +
                    "_Ps" + (int) (start) + "_Pe" + (int) (end) + "_P2s" + (int) (startBis) + "_P2e" + (int) (endBis) + "_TT" + (int) (tTime);
        }

    }
}
